home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / shells / cshel500 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-03-03  |  56.1 KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i028: CShell 5.00 - alternative command interface, Part02/06
  4. Reply-To: <umueller@iiic.ethz.ch>
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v91i028@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga:v91i027@ab20.larc.nasa.gov>
  8. Date: 03 Mar 91 21:56:05 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: <umueller@iiic.ethz.ch>
  14. Posting-number: Volume 91, Issue 028
  15. Archive-name: shells/cshell-5.00/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 6)."
  24. # Contents:  changes.doc rawcon.c sub.c
  25. # Wrapped by tadguy@ab20 on Sun Mar  3 16:55:58 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'changes.doc' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'changes.doc'\"
  29. else
  30. echo shar: Extracting \"'changes.doc'\" \(13639 characters\)
  31. sed "s/^X//" >'changes.doc' <<'END_OF_FILE'
  32. XOverview
  33. X
  34. XThe new CShell 4.9 is no longer adequate to low end systems, it's too large
  35. Xand  consumes  too  much memory.  I advise everybody who doesn't own a hard
  36. Xdrive  to stick with the old versions.  For those who can afford to run it,
  37. Xhowever,  this  version  is a practical tool in command mode and a powerful
  38. Xlanguage  for  writing  scripts  while  remaining  compatible  with its old
  39. Xscripts.   As the version number 4.9 suggests, I'm note quite done yet, and
  40. Xthere might be bugs left.  I count on you to report them to me.  The source
  41. Xis not included this time, but still available.
  42. X
  43. XSome of the new features:
  44. X
  45. X- works fine on an Amiga 3000 and under Kickstart 2.0
  46. X- is residentable
  47. X- file name completion with TAB
  48. X- freely programmable command line editing keys
  49. X- many new editing functions
  50. X- jump scrolling (three lines scrolled in one step, useful in interlace)
  51. X- automatic cd  (type 'system' instead of 'cd system')
  52. X- quick cd (cd knows about all directories on your HD and jumps directly)
  53. X- ~ stands for previous current directory
  54. X- special support for the closing kickstart 2.0 gadget
  55. X- you can 'rback' programs by adding a single '&' to the command line
  56. X- it is possible to install menus to the console window
  57. X- some internal functions csh have become faster 
  58. X- runs on VT terminals again, even command line editing works now
  59. X- many builtin functions now like 'echo @strleft( hello 3 )'
  60. X- you can finally use foreign character sets
  61. X- any letter can be coded using backslash: echo \101 ouputs 'A'
  62. X- more startup options: -b (priority -1) -t (terminal) -k (no ^C) etc.
  63. X- automatic rx-ing: you can 'rx' .rexx files by typing their name
  64. X- ^D now aborts batchfiles like under AmigaDOS
  65. X- will 'source' files with script bit set
  66. X- limit of 256 arguments removed
  67. X- limit of 20 commands per line removed
  68. X- limit of 256 bytes per source line extended to 512
  69. X
  70. XNew commands (and options):
  71. X
  72. X- 'addbuffers' accepts any number drive/buffer pairs
  73. X- 'action' sends a action request to a file class
  74. X- 'alias'es can have more than one argument
  75. X- 'alias'es can prevent wild card expansion
  76. X- 'ascii' shows an ascii table
  77. X- 'assign' accepts any number logical/physical pairs
  78. X- 'assign' can create late/nonbinding assigns under kick 2.0
  79. X- 'cd' has an option to generate the list of all your directories
  80. X- 'class' defines a class of files and the actions allowed on them
  81. X- 'close' without arguments closes all open files
  82. X- 'cls' clears the screen, but now also works on a vt terminal
  83. X- 'copy' now copies the protection bits but clears archive bit
  84. X- 'copy -f' now 'freshens' like zoo. NOTE: *incompatible* with 4.02
  85. X- 'date' has a stopwatch built in
  86. X- 'dir' can sort forwards and backwards by name, size or time.
  87. X- 'dir' can hide .info files and files with the h-bit set
  88. X- 'dir' can show differences between directories
  89. X- 'dir' can show filenotes and file types
  90. X- 'echo' has an option to print to stderr
  91. X- 'exec' works better now
  92. X- 'filenote' can display filenotes, too
  93. X- 'getenv' reads a ARP or ENV: environment variable
  94. X- 'head', a filter, displays the first n lines of stdin
  95. X- 'input' can get characters in single character mode (!)
  96. X- 'info' also gives information on a single device
  97. X- 'linecnt', a filter, counts number of lines
  98. X- 'man' gets documentation to a shell command
  99. X- 'mem' can show only chip, only fast or bytes used sinc last mem -s
  100. X- 'menu' adds a menu
  101. X- 'mv' now clears the archive bit
  102. X- 'path' can also be used to set the path, not only to list it
  103. X- 'protect' can clear and set bits without disturbing the others
  104. X- 'ps' by default only shows the basenames of the started commands
  105. X- 'qsort' quicksorts from stdin to stdout
  106. X- 'readfile' completely reads a file and stores it in a variable
  107. X- 'rxsend' can receive results (now it's useful!)
  108. X- 'search' is much faster and has new output
  109. X- 'setenv' is used to set ENV: variables
  110. X- 'tail', a filter, prints the last lines of a file
  111. X- 'tee' copies stdin to stdout and stderr
  112. X- 'truncate' cuts the width of an ascii file
  113. X- 'touch' now clears the archive bit
  114. X- 'uniq' removes consecutive identical lines
  115. X- 'usage' shows the usage of a command
  116. X- 'waitforport' waits for an (arexx) port
  117. X- 'whereis' looks for a file on your hard drive
  118. X
  119. XNew system variables:
  120. X
  121. X- '_every' contains a command to be executed before the prompt appears
  122. X- '_hilite' holds the highlighting attributes
  123. X- '_history' now can be set to 0, which disables history
  124. X- '_kick2x' indicates whether V36 dos.library could be opened
  125. X- '_lcd' is the last current directoy
  126. X- '_minrows' is the minimum number of rows a window must have to quickscroll
  127. X- '_nobreak', if set, disables ^C
  128. X- '_noreq' disables system requesters
  129. X- '_path' no more need slashes at the end of directories
  130. X- '_prompt' now has many special symbols like %t for current time
  131. X- '_qcd' holds the name of the file where the directoy list for cd is stored
  132. X- '_rxpath' stores the list of directories where .rexx files reside
  133. X- '_scroll' contains the scroll jump or 0 for no quick scrolling
  134. X- '_terminal' indicates wheter or not shell was started in terminal mode
  135. X- '_titlebar' can have special %-symbols like _prompt
  136. X- '_tool_xxx' holds default tools for file ending .xxx
  137. X- '_version' is the current shell version number
  138. X
  139. XFunctions:
  140. X
  141. X- @abbrev    is true if the str1 is an abbreviation of str2
  142. X- @abs       returns absolute value of <num>
  143. X- @appext    appends an extension to a string
  144. X- @availmem  returns free 'chip', 'fast' or otherwise total memory
  145. X- @basename  returns the file name without path
  146. X- @center    centers a string
  147. X- @checkport indicates if given port exists
  148. X- @clinum    returns the number of the given process
  149. X- @complete  returns the first word an abbreviation matches
  150. X- @concat    concats all args in one blank separated string
  151. X- @confirm   gets confirmation for all its arguments
  152. X- @dectohex  returns a string representing number in hex
  153. X- @delword   returns a string with the n-th word deleted.
  154. X- @delwords  deletes the next m words from the n-th.
  155. X- @dirs      returns the directories among the given file names
  156. X- @drive     outputs the drive ( device ) name associated to path
  157. X- @drives    outputs all available drives
  158. X- @exists    tells whether a file exists or not
  159. X- @fileblks  returns the # of blocks needed for the files
  160. X- @filelen   count the total number of bytes of the given files
  161. X- @fileprot  returns a string like ---arwed
  162. X- @filereq   brings up the arp file requester and returns the selected file
  163. X- @files     gives you the files among those names, no directories
  164. X- @freebytes the number of free bytes on the given path
  165. X- @freeblks  the number of free blocks on the given path
  166. X- @freestore the amount of free store on that path, given in K, M and G
  167. X- @getenv    returns the value of the named env: variable
  168. X- @howmany   indicates the # of shells running
  169. X- @index     returns the index of str2 in str1 (starting at 1)
  170. X- @info      the corresponding line from the 'info' command
  171. X- @intersect returns all words which are in both lists
  172. X- @lookfor   looks for a file in the current directory and the given paths
  173. X- @lower     lowercases its arguments
  174. X- @match     returns the words in the that match the arp-pattern
  175. X- @max       computes the maximum of all given numbers
  176. X- @megs      expresses a number in K, M and G (-bytes)
  177. X- @member    tells you if the first arg is among the remaining
  178. X- @min       computes the minimum of all given numbers
  179. X- @nameext   returns all after the last dot of filename.
  180. X- @nameroot  returns all before the LAST dot of filename.
  181. X- @union     returns all names that are in either list
  182. X- @pathname  strips the base name from a path
  183. X- @pickargs  picks of its arguments those which don't start with a '-'
  184. X- @pickopts  picks of its arguments those which start witch a '-'
  185. X- @rpn       computes the rpn expression. See rpn command
  186. X- @sortargs  sorts its arguments alphabetically
  187. X- @split     makes each blank separated part of @string a word
  188. X- @strcmp    returns -1, 0 or 1 depending of alphabetical comparison
  189. X- @strhead   see strhead command
  190. X- @strleft   see strleft command
  191. X- @strmid    see strmid command
  192. X- @strright  see strright command
  193. X- @strtail   see strtail command
  194. X- @subword   returns the n-th word of the given list
  195. X- @subword   returns the next m words word of the given list starting from n
  196. X- @tackon    see tackon command
  197. X- @unique    sorts the arguments and makes each of them unique
  198. X- @upper     upper cases the given words
  199. X- @volume    returns the volume name in that path or "" if no disk present
  200. X- @without   returns all names of list 1 that are not in list 2
  201. X- @word      same as @subword
  202. X- @words     returns the number of args
  203. X
  204. XBug fixes:
  205. X
  206. X- recursive wild card expansion does not crash the Amiga 3000 anymore
  207. X- recursive wild card expansion does not lose memory anymore
  208. X- now works on AUX:
  209. X- trying to start a non-object-file now properly prints 'Command Not Found'
  210. X- automatic sourcing now also works if you already add .sh to the file name
  211. X- files longer than 999999 bytes no longer misalign 'dir'
  212. X- exec does not discard the rest of the command line ('exec echo hi;echo ho')
  213. X- all memory trashing fixed. Thanks to C= for their great debugging tools!
  214. X- source doesn't forget last character if batchfile was not CR terminated
  215. X- run & rback also search AmigaDOS path now
  216. X- division by zero does not crash rpn anymore
  217. X- temporary pipe files are now written to t: instead of ram:
  218. X- shift-tab does not cause a lockup anymore
  219. X- running the shell via aux: no longer crashes the machine
  220. X- 'history partial' now numbers the lines correctly
  221. X- strleft, strright and strmid no longer crash on strings > 256 bytes
  222. X- source with no arguments now prints correct error message
  223. X- 'input' now cuts down lines longer than 256 bytes instead of crashing
  224. X- cursor-up no more deletes lines if there's an invalid entry in the history
  225. X- if history fails, no empty history entry is generated
  226. X- 'echo "---"' and even 'echo ---' work, but 'echo "-a"' still doesn't
  227. X- international character sets can be used
  228. X- 'copy -u' won't copy a file with identical date stamp but in uppercase
  229. X- 'copy -u' will no longer access low memory
  230. X- 'echo "echo mem | shell" | shell' now works, not only every second time
  231. X- starting from workbench now prevented
  232. X- editing lines longer than 256 bytes is now correctly prevented
  233. X- word-right cursor movement works correclty with multiple blanks
  234. X- 'if'-stack will be adjusted when a batch file is exited
  235. X- relabel occasionally crashed in Syquest drives. should be okay now
  236. X
  237. XNew to 4.02A:
  238. X
  239. X- Fixed bug that caused loss of memory on exit.
  240. X- cp now copies protection bits; use -f switch if you want to avoid this.
  241. X- Added  commands: man (and alias manlist), uniq, head, tail, tee.
  242. X- This doc has been reformatted to work with man.
  243. X
  244. XNew to 4.01A:
  245. X
  246. X- This version features mostly bug fixes and corrections:
  247. X * Window title is restored after quitting.
  248. X * rxrec now answers to the 'bye' message.
  249. X * rpn can now be redirected and piped; however, this causes
  250. X    some problem (see rpn for info).
  251. X * resident list now works with ARP 1.3. To recompile source, you must
  252. X    modify include file "libraries/arpbase.h".
  253. X    Change definition of rpn_Usage in struct ResidentProgramNode from LONG
  254. X    to WORD.
  255. X * pri no more assumes 20 CLI maximum.
  256. X * you can now split long lines in source files even into more than 2 lines.
  257. X- Added much info in this doc about source files (chapter XI)
  258. X- Added copyright notice (see under restrictions).
  259. X
  260. XNew to 4.00A:
  261. X
  262. X- This version is called 4.00A because it is not 100% compatible with
  263. X  previous versions. We choose to accept this in order to better support
  264. X  the new ARP.library 1.3.
  265. X- External commands are searched in a different order than before; Shell
  266. X  path is now searched AFTER current directory, AmigaDOS path and C:.
  267. X- ARP pattern matching has been implemented (in part for line arg expanding,
  268. X  fully for search -w).
  269. X- Internal changes for various optimizations.
  270. X- Search command has been improved in several ways.
  271. X- New commands: basename, tackon.
  272. X- New options: if -v, resident -d, fornum -v -s, dir -n.
  273. X- Fixed bugs with dir (some dirs remained locked), foreach -v, htype
  274. X  (blanks were treated as binary), info (for devices > 32M).
  275. X- rback command now works ok (run, however, doesn't).
  276. X- Oh, I forgot: it also has an AREXX port... And you don't even have to get
  277. X  AREXX to use it. See new commands rxsend, rxrec
  278. X
  279. XNew to 3.03A:
  280. X
  281. X- New filter commands fltlower, fltupper.
  282. X- Added configuration file feature: now if you have a file named S:.login,
  283. X  it will be sourced for every Shell you start.
  284. X- New option dir -c.
  285. X- New editing feature: shift-left(right) arrow move cursor to previous(next)
  286. X  word.
  287. X- Bugs fixed: alias command wasn't listed in help; typing a number as a
  288. X  command was interpreted like 'alias'.
  289. X
  290. XNew to 3.02A:
  291. X
  292. X- New commands: fornum, forline, strleft, strright, strmid, strlen, exec.
  293. X- Improved commands: foreach, pri.
  294. X- New system variable _clinumber.
  295. X- You can now split long lines in source files (see source for details).
  296. X- window -q now lists also position of screens/windows, not only dimension.
  297. X- Since strings are handled directly from Shell with new commands,
  298. X  rpn is now used only for calculations; string commands are gone.
  299. X  However, now RPN is really usable.
  300. X- Changed rawgets() to fix some problems with function keys, multi-line
  301. X  editing and window resizing; also, fixed bug with ^E.
  302. X- cat now warns you if it can't find any file matching your pattern.
  303. X- Now uses DOS packets to get ptr to CLI window; this fixes a bug that
  304. X  caused problems if Shell was run on unactive windows.
  305. X- Fixed minor bugs (htype printed some more ASCII bytes, some commands
  306. X  returned random values, history didn't print CR's).
  307. X- Heavy mods to this file.
  308. X
  309. END_OF_FILE
  310. if test 13639 -ne `wc -c <'changes.doc'`; then
  311.     echo shar: \"'changes.doc'\" unpacked with wrong size!
  312. fi
  313. # end of 'changes.doc'
  314. fi
  315. if test -f 'rawcon.c' -a "${1}" != "-c" ; then 
  316.   echo shar: Will not clobber existing file \"'rawcon.c'\"
  317. else
  318. echo shar: Extracting \"'rawcon.c'\" \(17773 characters\)
  319. sed "s/^X//" >'rawcon.c' <<'END_OF_FILE'
  320. X/*
  321. X * rawcon.c
  322. X *
  323. X * Shell 2.07M  17-Jun-87
  324. X * console handling, command line editing support for Shell
  325. X * using new console packets from 1.2.
  326. X * Written by Steve Drew. (c) 14-Oct-86.
  327. X * 16-Dec-86 Slight mods to rawgets() for Disktrashing.
  328. X *
  329. X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  330. X * Version 5.00L by Urban Mueller 17-Feb-91
  331. X *
  332. X */
  333. X
  334. X#include "shell.h"
  335. X
  336. Xstatic int myget( void );
  337. Xstatic void myunget(int c);
  338. Xstatic void setrawcon( long flag, int ievent );
  339. Xstatic int get_seq( long *param );
  340. Xstatic int bkspcword( int i, int max, int cnt );
  341. X
  342. X
  343. X#if RAW_CONSOLE
  344. X
  345. Xstatic char *tyahdptr, *lasttya;
  346. Xstatic int tabctr, qcdctr, unget;
  347. X
  348. X#define SETRAW setrawcon(-1L,1);
  349. X#define SETCON setrawcon( 0L,1);
  350. X
  351. Xint w_width;
  352. Xextern char *MenuCommand[MAXMENUS][MAXITEMS];
  353. X
  354. X#define CTRL  -64
  355. X#define SHIFT 512
  356. X#define ESC   1024
  357. X
  358. X#define CUP   256
  359. X#define CDN   257
  360. X#define CRT   258
  361. X#define CLT   259
  362. X#define TAB   9
  363. X
  364. Xstatic int Curmap;
  365. Xstatic USHORT *Keymap[8];
  366. Xstatic USHORT DefKeymap0[]={
  367. X       CLT,  0, /* CursLt = Move.Left  */
  368. X       CRT,  1, /* CursRt = Move.Right */
  369. X SHIFT+CLT,  2, /* SCursLt= Move.WordL */
  370. X SHIFT+CRT,  3, /* SCursRt= Move.WordR */
  371. X   ESC+CLT,  4, /* ESC-CLt= Move.SOL   */
  372. X   ESC+CRT,  5, /* ESC-CRt= Move.EOL   */
  373. X  CTRL+'A',  4, /* ^A     = Move.SOL   */
  374. X  CTRL+'E',  5, /* ^E     = Move.EOL   */
  375. X  CTRL+'Z',  4, /* ^Z     = Move.SOL   */
  376. X         8, 10, /* BackSp = Del.BackSp */
  377. X       127, 11, /* Delete = Del.Delete */
  378. X   ESC+  8, 12, /* ESC-BkS= Del.WordL  */
  379. X   ESC+127, 13, /* ESC-Del= Del.WordR  */
  380. X  CTRL+'W', 12, /* ^W     = Del.WordL  */
  381. X  CTRL+'B', 14, /* ^B     = Del.SOL    */
  382. X  CTRL+'K', 15, /* ^K     = Del.EOL    */
  383. X   ESC+'x',513, /* ESC-x  = Setmap 1   */
  384. X   ESC+'d', 16, /* ESC-d  = Del.Line   */
  385. X  CTRL+'X', 16, /* ^X     = Del.Line   */
  386. X       CUP, 20, /* CursUp = Hist.Back  */
  387. X       CDN, 21, /* CursDn = Hist.Forw  */
  388. X SHIFT+CUP, 22, /* SCursUp= Hist.Beg   */
  389. X SHIFT+CDN, 23, /* SCursDn= Hist.End   */
  390. X   ESC+'!', 24, /* ESC-!  = Hist.Compl */
  391. X   ESC+ 13, 25, /* ESC-Ret= Hist.Exec  */
  392. X  CTRL+'T', 26, /* ^T     = Hist.Tail  */
  393. X       TAB, 30, /* Tab    = Comp.Norm  */
  394. X SHIFT+TAB, 31, /* STab   = Comp.Part  */
  395. X   ESC+TAB, 32, /* ESC-TAB= Comp.All   */
  396. X   ESC+'c', 33, /* ESC-c  = Comp.CD    */
  397. X   ESC+'~', 34, /* ESC-~  = Comp.LastCD*/
  398. X   ESC+'i', 40, /* ESC-i  = Spec.Insert*/
  399. X  CTRL+'L', 43, /* ^L     = Spec.Refr  */
  400. X        10, 44, /* Enter  = Spec.Accept*/
  401. X        13, 44, /* ^Enter = Spec.Accept*/
  402. X  CTRL+'N', 45, /* ^N     = Spec.Next  */
  403. X  CTRL+'O', 48, /* ^O     = Spec.EchoO */
  404. X CTRL+'\\', 46, /* ^\     = Spec.EOF   */
  405. X       260, 42, /* Help   = Misc.Help  */
  406. X       271, 51, /* Menu   = Menu       */
  407. X  CTRL+'U', 52, /* Undo   = Spec.Undo  */
  408. X  CTRL+'R', 53, /* Repeat = Spec.Repeat*/
  409. X         0,  0
  410. X};
  411. X
  412. Xstatic USHORT DefKeymap1[]={
  413. X         8, 14,
  414. X       127, 15
  415. X};
  416. X
  417. Xstatic char *Line, *Prompt;
  418. Xstatic int Pl;
  419. Xstatic char LastDir[128];
  420. X
  421. Xvoid
  422. Xinitmap(void)
  423. X{
  424. X    if( !Keymap[0] )
  425. X        Keymap[0]=DefKeymap0, Keymap[1]=DefKeymap1;
  426. X}
  427. X
  428. Xchar *
  429. Xrawgets( char line[], char prompt[] )
  430. X{
  431. X    static int inslen, lastrecall=-1;
  432. X    static int lastfn, lastkey;
  433. X
  434. X    int    n, pl, max, i, c, key, fn, cnt;
  435. X    USHORT *p;
  436. X    char   *s, *ps, typeahd[256], undo[256];
  437. X    int    savn, insert=1, recall, undo_i, undo_max;
  438. X    struct HIST *hist;
  439. X    char   **eav=NULL, *ret, fake;
  440. X    int    eac, eactr;
  441. X    long   param[10], *par;
  442. X
  443. X    typeahd[0]=0;
  444. X    tyahdptr=lasttya=typeahd;
  445. X
  446. X    newwidth();
  447. X
  448. X    if ( o_noraw || !IsInteractive(Input()) ) {
  449. X        if( IsInteractive(Input())) {
  450. X            printf("%s",prompt);
  451. X            fflush(stdout);
  452. X        }
  453. X        return(gets(line));
  454. X    }
  455. X
  456. X    if (WaitForChar((long)Input(), 100L) ||   /* don't switch to 1L ...*/
  457. X            CHARSWAIT(stdin)) {               /* else causes read err's*/
  458. X        gets(line);
  459. X        return(line);
  460. X    }
  461. X
  462. X    SETRAW;
  463. Xbegin:
  464. X    printf("\015%s\033[6n",prompt);
  465. X    fake= savn = pl = n = 0;
  466. X    tyahdptr = typeahd;
  467. X
  468. X    while( (typeahd[n]=getchar()) != 'R') {
  469. X        if (typeahd[n] == 155) savn = n;
  470. X        if (typeahd[n] == 27 && getchar()=='[')
  471. X            typeahd[n] =155, savn=n;
  472. X        n++;
  473. X    }
  474. X    /* typeahd now contains possible type a head chars
  475. X       followed by <CSI> cursor position report. */
  476. X
  477. X    typeahd[savn]  = '\0';
  478. X    if (typeahd[n-2] != ';') pl = (typeahd[n-2] -'0') * 10;
  479. X    pl += typeahd[n-1] - 49;
  480. X    ps = line + pl;
  481. X    line[max = i = pl] = '\0';
  482. X
  483. X    Line=line; Prompt=prompt; Pl=pl;
  484. X
  485. X    if (s = get_var (LEVEL_SET, "_insert")) insert = atoi(s) ? 1 : 0;
  486. X
  487. X    if( (recall=lastrecall)>=0 ) {
  488. X        lastrecall=-1;
  489. X        goto recallh;
  490. X    }
  491. X
  492. X    while( (c=myget()) != -1) {
  493. X        int esc=0;
  494. X        key=-1;
  495. X        if( c==27 ) esc=ESC, c=myget();
  496. X        switch(c) {
  497. X        case 155:
  498. X            switch(c=myget()) {
  499. X            case 'A': key=256;       break; /* CursUp */
  500. X            case 'B': key=257;       break; /* CursDn */
  501. X            case 'C': key=258;       break; /* CursRt */
  502. X            case 'D': key=259;       break; /* CursLt */
  503. X            case 'T': key=256+SHIFT; break; /* SCursUp */
  504. X            case 'S': key=257+SHIFT; break; /* SCursDn */
  505. X            case ' ':
  506. X                switch( myget() ) {
  507. X                case '@': key=258+SHIFT; break; /* SCursRt */
  508. X                case 'A': key=259+SHIFT; break; /* SCursLt */
  509. X                } break;
  510. X            case 'Z': key=9+SHIFT;       break; /* STab    */
  511. X            case '?': key=260; myget();  break; /* Help    */
  512. X            default :
  513. X                myunget(c);
  514. X                par=param;
  515. X                do {
  516. X                    for( *par=0; (c=myget())>='0' && c<='9';  )
  517. X                        *par=10* *par + c-'0';
  518. X                    par++;
  519. X                } while( c==';' );
  520. X                if( c=='~' ) {
  521. X                    key=param[0]+261;
  522. X                    if( key>270 ) key+=SHIFT-10;
  523. X                }
  524. X                if( c=='|' ) key=271;
  525. X            } break;
  526. X        default: key=c; break;
  527. X        }
  528. X        key+=esc;
  529. X
  530. X        for( fn=-1, p=Keymap[Curmap]; *p; p+=2 )
  531. X            if( *p==key )
  532. X                { fn=p[1]; break; }
  533. X        if( fn==-1 && key>=261 && key<=270 || key>=261+SHIFT && key<=270+SHIFT )
  534. X            fn=50;
  535. X
  536. X        if( fn!=52 && !*lasttya) {
  537. X            memcpy( undo+pl, line+pl, max-pl );
  538. X            undo_i=i; undo_max=max;
  539. X        }
  540. X
  541. X        switch( fn/512 ) {
  542. X        case 1:
  543. X            fn&=511;
  544. X            if( fn<8 && Keymap[fn] ) Curmap=fn;
  545. X            fn=-2;
  546. X            break;
  547. X        case 2:
  548. X            key=fn&511, fn=-1;
  549. X            break;
  550. X        }
  551. X
  552. X        if( fn!=-2 )
  553. X            Curmap=0;
  554. X
  555. X        if( fn!=53 && !*lasttya )
  556. X            lastfn=fn, lastkey=key;
  557. X
  558. Xdofn:
  559. X        switch( fn ) {
  560. X        case -2:
  561. X            break;
  562. X
  563. X        case 0:                                 /* cursor left  */
  564. X            if (i > pl) 
  565. X                i--, printf("\033[D");
  566. X            break;
  567. X        case 1:                                 /* cursor right */
  568. X            if (i < max)
  569. X                i++, printf("\033[C");
  570. X            break;
  571. X        case 2:                                 /* word left    */
  572. X            for (cnt=0; i>pl && line[i-1] == ' '; cnt++,i--); 
  573. X            for (     ; i>pl && line[i-1] != ' '; cnt++,i--);
  574. X            if( cnt ) printf("\033[%dD",cnt);
  575. X            break;
  576. X        case 3:                                 /* word right   */
  577. X            for( cnt=0; i<max && line[i] != ' '; i++,cnt++) ;
  578. X            for(      ; i<max && line[i] == ' '; i++,cnt++) ;
  579. X            if( cnt ) printf("\033[%dC",cnt);
  580. X            break;
  581. X        case 4:                                 /* beg of line  */
  582. X            if (i>pl) printf("\033[%dD",i-pl);
  583. X            i = pl;
  584. X            break;
  585. X        case 5:                                 /* end of line  */
  586. X            if (i!=max) printf("\033[%dC",max - i);
  587. X            i = max;
  588. X            break;
  589. X
  590. X        case 10:                                /* backspace    */
  591. X            if (i > pl) {
  592. X                i--;
  593. X                printf("\010");
  594. X            } else break;
  595. X        case 11:                                /* delete       */
  596. X            if (i < max) {
  597. X                int j,t,l = 0;
  598. X                memmove(&line[i],&line[i+1],max-i);
  599. X                --max;
  600. X                printf("\033[P");
  601. X                j = w_width - i % w_width - 1;  /* amount to end */
  602. X                t = max/w_width - i/w_width;    /* no of lines   */
  603. X                for(n = 0; n < t; n++) {
  604. X                    l += j;                     /* # of char moved*/
  605. X                    if (j) printf("\033[%dC",j);/* goto eol       */
  606. X                    printf("%c\033[P",line[w_width*(i/w_width+n+1)-1]);
  607. X                    j = w_width-1;
  608. X                }
  609. X                if (t)
  610. X                    printf("\033[%dD",l+t);     /* get back       */
  611. X            }
  612. X            break;
  613. X        case 12:                                /* bkspc word     */
  614. X            cnt= bkspcword(i,max,-1);
  615. X            max-=cnt; i-=cnt;
  616. X            break;
  617. X        case 13:
  618. X            for( cnt=0; i<max && line[i]!=' '; i++,cnt++ ) ;
  619. X            for(      ; i<max && line[i]==' '; i++,cnt++ ) ;
  620. X            if ( cnt ) printf("\033[%dC",cnt);
  621. X            cnt=bkspcword(i,max,cnt);
  622. X            i-=cnt; max-=cnt;
  623. X            break;
  624. X        case 14:
  625. X            cnt=bkspcword(i,max,i-pl);
  626. X            i-=cnt; max-=cnt;
  627. X            break;
  628. X        case 16:                                /* delete line    */
  629. X            if (i>pl) printf("\033[%dD",i-pl);
  630. X            i = pl;
  631. X        case 15:                                /* delete to EOL  */
  632. X            printf("\033[J");
  633. X            max = i;
  634. X            line[i] = '\0';
  635. X            break;
  636. X
  637. X
  638. X        case 20:                                /* history up   */
  639. X            ++recall;
  640. X        case 21:                                /* history down */
  641. X            line[pl] = '\0';
  642. X            if (recall >= 0 || fn==20) {
  643. X                if ( fn==21 ) --recall;
  644. Xrecallh:
  645. X                n=recall;
  646. X                if (recall >= 0) {
  647. X                    for(hist = H_head; hist && n--;
  648. X                    hist = hist->next);
  649. X                    if (hist) strcpy(&line[pl],hist->line);
  650. X                    else recall = H_len;
  651. X                }
  652. X            }
  653. X            if (i != pl)
  654. X                printf("\033[%dD",i-pl);
  655. X            printf("\033[J%s",ps);
  656. X            i = max = strlen(ps) + pl;
  657. X            break;
  658. X        case 22:                                /* beg of hist */
  659. X            recall = H_len-1;
  660. X        case 23:                                /* end of hist */
  661. X            line[pl] = '\0';
  662. X            if (fn == 23) {
  663. X                recall = 0;
  664. X                if (H_head) strcpy(&line[pl], H_head->line);
  665. X            } else if (H_tail)
  666. X                strcpy(&line[pl], H_tail->line);
  667. X            printf("\015\033[J%s%s", prompt, ps);
  668. X            i = max = strlen(ps) + pl;
  669. X            break;
  670. X        case 24:                                /* complete hist */
  671. X            line[max]=0;
  672. X            if( s=get_history(&line[pl-1],0 )) {
  673. X                if (i>pl) printf("\033[%dD\033[J",i-pl);
  674. X                line[i=max=pl]=0;
  675. X                strncpy(typeahd,s,256);
  676. X                tyahdptr=typeahd;
  677. X            }
  678. X            break;
  679. X        case 25:                                /* exec hist  */
  680. X            lastrecall= recall;
  681. X            goto done;
  682. X        case 26:                                /* tail of prev */
  683. X            if( H_head && (s=H_head->line) && (s=index(s,' ')) )
  684. X                tyahdptr=s;
  685. X            break;
  686. X
  687. X        case 30:                                /* complete */
  688. X        case 31:
  689. X        case 32:
  690. X        case 33: {
  691. X            static int lastcompl;
  692. X            int j, k, n, e, cnt, len, radlen;
  693. X            char *name, *q, abbrev;
  694. X
  695. X            abbrev= fn==31;
  696. Xcomplete:
  697. X            tyahdptr="";
  698. X            if( tabctr!=0 ) {
  699. X                char *dest=typeahd, *lcd;
  700. X
  701. X                lastcompl=fn;
  702. X                for( cnt=0; i<max && line[i]!=' '; ++i, ++cnt ) ;
  703. X                if(cnt) printf("\033[%dC",cnt);
  704. X                for( e=i, j=i-1, cnt=0; j>=pl && line[j]!=' ' && line[j]!='<' &&
  705. X                                 line[j]!='>' && line[j]!=';' ; --j ) cnt++;
  706. X                ++j;
  707. X
  708. X                if( line[j]=='~' && (lcd=get_var(LEVEL_SET,v_lcd))) {
  709. X                    strcpy(dest,lcd);
  710. X                    dest+=strlen(dest);
  711. X                    j++;
  712. X                }
  713. X                memcpy(dest,&line[j],e-j);
  714. X                dest+=e-j;
  715. X                if( fn!=33 )
  716. X                    *dest++='*';
  717. X                *dest=0;
  718. X                if( eav ) free_expand( eav ), eav=NULL;
  719. X                breakreset();
  720. X                tabctr=1;
  721. X                if( fn==33 ) {
  722. X                    strncpy(LastDir,typeahd,128);
  723. X                    if( !quick_cd( name=typeahd+128, LastDir, 0))
  724. X                        { putchar(7); break; }
  725. X                } else {
  726. X                    eav =expand(typeahd,&eac);
  727. X                    if( eac==0 ) { putchar(7); break; }
  728. X                    QuickSort(eav, eac);
  729. X                    if( fn==30 )
  730. X                        name=eav[ eactr=0 ];
  731. X                    else
  732. X                        name=compile_av(eav,0,eac,' ',1), tabctr=0;
  733. X                } 
  734. X                inslen=cnt;
  735. X            } else {
  736. X                abbrev=0, tabctr=1;
  737. X                if( lastcompl==33 ) {
  738. X                    quick_cd( name=typeahd+128, LastDir, 1);
  739. X                } else {
  740. X                    if( !eac ) break;
  741. X                    name=eav[eactr=++eactr % eac];
  742. X                }
  743. X            }
  744. X            len=bkspcword(i,max,inslen);
  745. X            i-=len; max-=len;
  746. X            if( abbrev && eac>1) {
  747. X                strcpy( typeahd, eav[0] );
  748. X                radlen= 9999;
  749. X                for( k=0; k<eac; k++ ) {
  750. X                    if ( (n=strlen(eav[k])) < radlen ) radlen=n;
  751. X                    for( n=0; n<radlen && eav[0][n]==eav[k][n]; n++ ) ;
  752. X                    if ( n<radlen ) radlen=n;
  753. X                }
  754. X                typeahd[radlen]=0;
  755. X                eactr--;
  756. X            } else {
  757. X                if( lastcompl==32 ) {
  758. X                    strncpy( typeahd,name,250 );
  759. X                    name[250]=0;
  760. X                } else {
  761. X                    strcpy(typeahd,(q=index( name, ' ' )) ? "\"" : "" );
  762. X                    strcat(typeahd,name);
  763. X                    if( q ) strcat(typeahd,"\"");
  764. X                    if( lastcompl==33 || isdir(name) )
  765. X                        appendslash( typeahd );
  766. X                    else 
  767. X                        strcat( typeahd, " " );
  768. X                }
  769. X            }
  770. X            tyahdptr=typeahd;
  771. X            inslen=strlen(typeahd);
  772. X            }
  773. X            break;
  774. X        case 34:
  775. X            strncpy(typeahd,get_var( LEVEL_SET, v_lcd ),230);
  776. X            appendslash(tyahdptr=typeahd);
  777. X            break;
  778. X
  779. X        case 40:                      /* ins/ovr */
  780. X            insert ^= 1;
  781. X            break;
  782. X        case 41:                      /* quit */
  783. X            strcpy(ps,"quit");
  784. X            goto done;
  785. X        case 42:                      /* help */
  786. X            strcpy(ps,"help");
  787. X            goto done;
  788. X        case 43:                      /* refresh   */
  789. X            if ((n = i/w_width)) printf("\033[%dF",n);
  790. X            printf("\015\033[J%s%s",prompt,ps);
  791. X            i = max;
  792. X            break;
  793. X        case 44:
  794. X            line[max] = '\0';
  795. Xdone:        printf("\033[%dC\n",max - i);
  796. X            strcpy(line, ps);
  797. X            ret=line;
  798. X            if( fake ) goto begin;
  799. X            goto exit;
  800. X        case 45:                      /* leave   */
  801. X            line[max] = '\0';
  802. X            add_history( ps );
  803. X            fake=1;
  804. X            goto done;
  805. X        case 46:                      /* EOF */
  806. X            ret=NULL;
  807. X            goto exit;
  808. X        case 47:
  809. X            break;
  810. X        case 48:
  811. X            printf("\017");
  812. X            break;
  813. X        case 49:
  814. X            printf("\07");
  815. X            break;
  816. X
  817. X        case 50: {
  818. X            char fkeys[8];
  819. X            sprintf(fkeys,"%c%d",param[0]>=10?'F':'f',param[0]%10+1);
  820. X            if (s = get_var(LEVEL_SET, fkeys)) {
  821. X                tyahdptr = strcpy(typeahd,s);
  822. X                a0tospace( tyahdptr );
  823. X            }
  824. X            break;
  825. X            }
  826. X        case 51: {
  827. X            int class=param[0], code=param[2];
  828. X            if( class==10 ) {
  829. X                int num=MENUNUM( code ), item=ITEMNUM( code );
  830. X                tyahdptr="";
  831. X                if( num>=0 && num<MAXMENUS && item>=0 && item<=MAXITEMS )
  832. X                    tyahdptr=MenuCommand[num][item];                                 
  833. X            }
  834. X            if( class==11 ) {
  835. X                strcpy(ps,"quit");
  836. X                goto done;
  837. X            }
  838. X            }
  839. X        case 52: {
  840. X            int t;
  841. X
  842. X            if ((n = i/w_width)) printf("\033[%dF",n);
  843. X            swapmem( undo+pl, line+pl, MAX( max, undo_max)-pl );
  844. X            t=max; max=undo_max; undo_max=t;
  845. X            t=i;   i  =undo_i;   undo_i  =t;
  846. X            line[max]=0;
  847. X            printf("\015\033[J%s%s",prompt,ps);
  848. X            if( i<max ) printf("\033[%dD",max-i);
  849. X            }
  850. X            break;
  851. X        case 53:
  852. X            fn=lastfn; key=lastkey;
  853. X            goto dofn;
  854. X
  855. X        default:
  856. X            key&=255;
  857. X            if (key == 9) key = 32;
  858. X            if (key > 31 && (insert?max:i) < 256) {
  859. X                if (i < max && insert) {
  860. X                    int j,t,l = 0;
  861. X                    memmove(&line[i+1], &line[i], max - i);
  862. X                    printf("\033[@%c",key);
  863. X                    t = max/w_width - i/w_width;
  864. X                    j = w_width - i % w_width - 1;
  865. X                    for(n = 0; n < t; n++) {
  866. X                        l += j;
  867. X                        if (j) printf("\033[%dC",j);
  868. X                        printf("\033[@%c",line[w_width*(i/w_width+n+1)]);
  869. X                        j = w_width-1;
  870. X                    }
  871. X                    if (t) printf("\033[%dD",l + t);
  872. X                    ++max;
  873. X                }
  874. X                else {
  875. X                    if(i == pl && max == i) printf("\015%s%s",prompt,ps);
  876. X                    putchar(key);
  877. X                }
  878. X                line[i++] = key;
  879. X                if (max < i) max = i;
  880. X                line[max] = '\0';
  881. X            }
  882. X        }
  883. X    }
  884. X    ret=NULL;
  885. Xexit:
  886. X    newwidth();
  887. X    if( eav ) free_expand(eav);
  888. X    SETCON;
  889. X    return ret;
  890. X}
  891. X
  892. Xint
  893. Xbkspcword( int i, int max, int cnt )
  894. X{
  895. X    int o=i;
  896. X
  897. X    if( !cnt ) return 0;
  898. X
  899. X    if( cnt==-1 ) {
  900. X        cnt=0;
  901. X        while( i>Pl && Line[i-1]==' ' )  i--, cnt++;
  902. X        while( i>Pl && Line[i-1]!=' ' )  i--, cnt++;
  903. X    } else 
  904. X        i-=cnt;
  905. X
  906. X    if( cnt ) printf("\033[%dD",cnt);
  907. X    memmove( Line+i, Line+o, max-o );
  908. X    memset ( Line+max-cnt, ' ', cnt  );
  909. X    
  910. X    printf("%s",Line+i);
  911. X    
  912. X    if( max-i ) printf("\033[%dD", max-i );
  913. X    fflush(stdout);
  914. X    Line[max-=cnt]=0;
  915. X
  916. X    return cnt;
  917. X}
  918. X
  919. Xvoid
  920. Xsetrawcon( long flag, int ievent ) /* -1L=RAW:, 0L=CON: */
  921. X{
  922. X    static char menuon, button;
  923. X    long packargs[8];
  924. X
  925. X    if( !o_nowindow && ievent && flag==0 && menuon)
  926. X        printf("\033[10}"), menuon=0;
  927. X
  928. X    packargs[0]=flag;
  929. X    SendPacket(994L, packargs, (void *)Myprocess->pr_ConsoleTask);
  930. X
  931. X    if( !o_nowindow && ievent && flag==-1 ) {
  932. X        if( !menuon )
  933. X            printf("\033[10{"), menuon=1;
  934. X        if( !button )
  935. X            printf("\033[11{"), button=1;
  936. X    }
  937. X}
  938. X
  939. X
  940. X
  941. Xstatic int row, height, cnt, noquick=1;
  942. Xstatic char scrollstr[10];
  943. X
  944. Xextern char *Cin_name, *Cout_name;
  945. Xextern BPTR OldCin;
  946. X
  947. Xstatic int FromTee;
  948. X
  949. Xvoid
  950. Xprepscroll( int fromtee )
  951. X{
  952. X    BPTR truecin=0;
  953. X    long param[8];
  954. X
  955. X    row=height=0;
  956. X    FromTee=fromtee;
  957. X
  958. X    if(( noquick=!o_scroll ||o_noraw || o_nofastscr ))
  959. X        return;
  960. X    if(( noquick=Cout_name && !fromtee ))
  961. X        return;
  962. X    if( Cin_name ) {
  963. X        truecin=Myprocess->pr_CIS;
  964. X
  965. X        if( noquick=!IsInteractive(OldCin) )
  966. X            return;
  967. X
  968. X        Myprocess->pr_CIS = DEVTAB(stdin) = OldCin;
  969. X    }
  970. X
  971. X    if( !CHARSWAIT(stdin) ) {
  972. X        SETRAW;
  973. X        fprintf(fromtee?stderr:stdout,"\033[ q");
  974. X        get_seq( param );
  975. X        height=param[2];
  976. X        while( getchar()!='r') ;
  977. X
  978. X        fprintf(fromtee?stderr:stdout,"\033[6n");
  979. X        get_seq( param );
  980. X        row=param[0];
  981. X
  982. X        SETCON;
  983. X
  984. X        cnt= height-row+1;
  985. X        noquick= height<o_minrows;
  986. X    }
  987. X
  988. X    sprintf(scrollstr,"\033[%cS\033[%cA", o_scroll+'0', o_scroll+'0');
  989. X
  990. X    if( truecin )
  991. X        Myprocess->pr_CIS = DEVTAB(stdin) = truecin;
  992. X}
  993. X
  994. Xstatic int
  995. Xget_seq( long *param )
  996. X{
  997. X    int c;
  998. X
  999. X    while( (c=getchar())!=155 ) ;
  1000. X    do {
  1001. X        *param=0;
  1002. X        while( (c=getchar())>='0' && c<='9' )
  1003. X            *param=10* *param + c-'0';
  1004. X        param++;
  1005. X    } while( c==';' );
  1006. X
  1007. X    return c;
  1008. X}
  1009. X
  1010. X
  1011. Xvoid
  1012. Xquickscroll( void )
  1013. X{
  1014. X    if( noquick ) return;
  1015. X
  1016. X    if( --cnt<=0 ) {
  1017. X        cnt=o_scroll;
  1018. X        fprintf( FromTee ? stderr : stdout, "%s",scrollstr);
  1019. X    }
  1020. X}
  1021. X
  1022. Xint
  1023. Xdo_keymap( void )
  1024. X{
  1025. X    int i, n, len;
  1026. X    USHORT *tmp, *put, *get, *map;
  1027. X    char   *ind;
  1028. X
  1029. X    n=myatoi(av[1],0,7);
  1030. X    if( atoierr ) return 20;
  1031. X
  1032. X    map=Keymap[n]; len=0;
  1033. X    if( map )
  1034. X        for( len=0; map[2*len]; len++ ) ;
  1035. X
  1036. X    put=tmp=malloc((len+ac)*2*sizeof(USHORT));
  1037. X    for( i=2; i<ac; i++ ) {
  1038. X        if( !(ind=index(av[i],'='))) {
  1039. X            ierror( av[i],500);
  1040. X            free( tmp );
  1041. X            return 20;
  1042. X        }
  1043. X        *put++=atoi(av[i]);
  1044. X        *put++=atoi(ind+1);
  1045. X    }
  1046. X
  1047. X    for( i=0; i<len; i++ ) {
  1048. X        for( get=tmp; get<put; get+=2 )
  1049. X            if( *get==map[2*i] )
  1050. X                break;
  1051. X        if( get==put ) {
  1052. X            *put++=map[2*i];
  1053. X            *put++=map[2*i+1];
  1054. X        }
  1055. X    }
  1056. X
  1057. X    if( map && map!=DefKeymap0 && map!=DefKeymap1 )
  1058. X        free( map );
  1059. X    Keymap[n]=tmp;
  1060. X    Curmap=0;
  1061. X
  1062. X    return 0;
  1063. X}
  1064. X
  1065. Xstatic int
  1066. Xmyget( void )
  1067. X{
  1068. X    int c;
  1069. X
  1070. X    lasttya=tyahdptr;
  1071. X    if( unget )
  1072. X        c=unget, unget=0;
  1073. X    else if( tyahdptr && *tyahdptr)
  1074. X        c=*tyahdptr++;
  1075. X    else {
  1076. X#ifndef AZTEC_C
  1077. X        fflush(stdout);
  1078. X#endif
  1079. X        if( (c=getchar())!=155 )
  1080. X            tabctr--, qcdctr--;
  1081. X    }
  1082. X
  1083. X    return c;
  1084. X}
  1085. X
  1086. Xstatic void
  1087. Xmyunget(int c)
  1088. X{
  1089. X    unget=c;
  1090. X}
  1091. X
  1092. Xint
  1093. Xnewwidth( void )
  1094. X{
  1095. X    extern struct Window *Win;
  1096. X
  1097. X    if( !o_nowindow && Win )
  1098. X        w_width=(Win->Width-(Win->BorderLeft+Win->BorderRight))/
  1099. X                 Win->RPort->TxWidth;
  1100. X    else
  1101. X        w_width=80;
  1102. X    return w_width;
  1103. X}
  1104. X
  1105. X
  1106. X
  1107. X#else
  1108. X
  1109. Xprepscroll(){}
  1110. Xquickscroll(){}
  1111. X
  1112. X#endif
  1113. X
  1114. END_OF_FILE
  1115. if test 17773 -ne `wc -c <'rawcon.c'`; then
  1116.     echo shar: \"'rawcon.c'\" unpacked with wrong size!
  1117. fi
  1118. # end of 'rawcon.c'
  1119. fi
  1120. if test -f 'sub.c' -a "${1}" != "-c" ; then 
  1121.   echo shar: Will not clobber existing file \"'sub.c'\"
  1122. else
  1123. echo shar: Extracting \"'sub.c'\" \(21051 characters\)
  1124. sed "s/^X//" >'sub.c' <<'END_OF_FILE'
  1125. X
  1126. X/*
  1127. X * SUB.C
  1128. X *
  1129. X * (c)1986 Matthew Dillon     9 October 1986
  1130. X *
  1131. X * Version 2.07M by Steve Drew 10-Sep-87
  1132. X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  1133. X * Version 5.00L by Urban Mueller 17-Feb-91
  1134. X *
  1135. X */
  1136. X
  1137. X#include "shell.h"
  1138. X#include "proto.h"
  1139. X
  1140. Xstatic void del_history( void );
  1141. Xstatic int hasspace( char *s );
  1142. Xstatic int dnext( struct DPTR *dp, char **pname, int *stat);
  1143. Xstatic char *svfile( char *s1, char *s2, FIB *fib);
  1144. Xstatic int exall( BPTR lock, char *path );
  1145. Xstatic void quicksort( char **av, int n );
  1146. X
  1147. X
  1148. X#define HM_STR 0              /* various HISTORY retrieval modes */
  1149. X#define HM_REL 1
  1150. X#define HM_ABS 2
  1151. X
  1152. Xvoid
  1153. Xseterr( void )
  1154. X{
  1155. X    char buf[32], *val;
  1156. X    int stat=0;
  1157. X
  1158. X    sprintf(buf, "%d", Lastresult);
  1159. X    set_var(LEVEL_SET, v_lasterr, buf);
  1160. X    if( val=get_var(LEVEL_SET, v_stat))
  1161. X        stat = atoi(val);
  1162. X    if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
  1163. X}
  1164. X
  1165. X#define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0)
  1166. X
  1167. Xchar *
  1168. Xnext_word( char *str )
  1169. X{
  1170. X    while (*str && ! ISSPACE(*str)) ++str;
  1171. X    while (*str &&   ISSPACE(*str)) ++str;
  1172. X    return str;
  1173. X}
  1174. X
  1175. Xstatic int
  1176. Xhasspace( char *s )
  1177. X{
  1178. X    for ( ; *s; s++)
  1179. X        if (ISSPACE(*s)) return 1;
  1180. X    return 0;
  1181. X}
  1182. X
  1183. Xchar *
  1184. Xcompile_av(char **av, int start, int end, char delim, int quote)
  1185. X{
  1186. X    char *cstr, *p;
  1187. X    int len, i;
  1188. X
  1189. X    len = 1;
  1190. X    for (i = start; i < end; ++i) len += strlen(av[i]) + 3;
  1191. X    p = cstr = malloc(len);
  1192. X    *cstr = '\0';
  1193. X    for (i = start; i < end; ++i) {
  1194. X        if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
  1195. X        if (quote && hasspace(av[i]))
  1196. X            p += sprintf(p, "\"%s\"", av[i]);
  1197. X        else
  1198. X            p += sprintf(p, "%s",     av[i]);
  1199. X        if (i+1 < end) *p++=delim;
  1200. X    }
  1201. X    *p='\0';
  1202. X    return cstr;
  1203. X}
  1204. X
  1205. X/*
  1206. X * FREE(ptr)   --frees without actually freeing, so the data is still good
  1207. X *               immediately after the free.
  1208. X */
  1209. X
  1210. X
  1211. Xvoid
  1212. XFree( void *ptr )
  1213. X{
  1214. X    static char *old_ptr;
  1215. X
  1216. X    if (old_ptr) free (old_ptr);
  1217. X    old_ptr = ptr;
  1218. X}
  1219. X
  1220. X/*
  1221. X * Add new string to history (H_head, H_tail, H_len,
  1222. X *  S_histlen
  1223. X */
  1224. X
  1225. Xvoid
  1226. Xadd_history( char *str )
  1227. X{
  1228. X    struct HIST *hist;
  1229. X    char *get;
  1230. X
  1231. X    for( get=str; *get; get++ )
  1232. X        if( (*get&127)<' ')
  1233. X            *get=' ';
  1234. X
  1235. X    if (H_head != NULL && !strcmp(H_head->line, str))
  1236. X        return;
  1237. X    while (H_len > S_histlen)
  1238. X        del_history();
  1239. X    hist = (struct HIST *)malloc (sizeof(struct HIST));
  1240. X    if (H_head == NULL) {
  1241. X        H_head = H_tail = hist;
  1242. X        hist->next = NULL;
  1243. X    } else {
  1244. X        hist->next = H_head;
  1245. X        H_head->prev = hist;
  1246. X        H_head = hist;
  1247. X    }
  1248. X    hist->prev = NULL;
  1249. X    hist->line = malloc (strlen(str) + 1);
  1250. X    strcpy (hist->line, str);
  1251. X    ++H_len;
  1252. X}
  1253. X
  1254. Xstatic void
  1255. Xdel_history()
  1256. X{
  1257. X    if (H_tail) {
  1258. X        --H_len;
  1259. X        ++H_tail_base;
  1260. X        free (H_tail->line);
  1261. X        if (H_tail->prev) {
  1262. X            H_tail = H_tail->prev;
  1263. X            free (H_tail->next);
  1264. X        H_tail->next = NULL;
  1265. X        } else {
  1266. X            free (H_tail);
  1267. X            H_tail = H_head = NULL;
  1268. X        }
  1269. X    }
  1270. X}
  1271. X
  1272. Xchar *
  1273. Xget_history( char *ptr, int echo )
  1274. X{
  1275. X    struct HIST *hist;
  1276. X    int len;
  1277. X    int mode = HM_REL;
  1278. X    int num  = 1;
  1279. X    char *str;
  1280. X    char *result = NULL;
  1281. X
  1282. X    if (ptr[1] >= '0' && ptr[1] <= '9') {
  1283. X        mode = HM_ABS;
  1284. X        num  = atoi(&ptr[1]);
  1285. X        goto skip;
  1286. X    }
  1287. X    switch (ptr[1]) {
  1288. X    case '!':
  1289. X        break;
  1290. X    case '-':
  1291. X        num += atoi(&ptr[2]);
  1292. X        break;
  1293. X    default:
  1294. X        mode = HM_STR;
  1295. X        str  = ptr + 1;
  1296. X        break;
  1297. X    }
  1298. Xskip:
  1299. X    switch (mode) {
  1300. X    case HM_STR:
  1301. X        len = strlen(str);
  1302. X        for (hist = H_head; hist; hist = hist->next) {
  1303. X            if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  1304. X                result = hist->line;
  1305. X                break;
  1306. X            }
  1307. X        }
  1308. X        break;
  1309. X    case HM_REL:
  1310. X        for (hist = H_head; hist && num--; hist = hist->next);
  1311. X        if (hist)
  1312. X        result = hist->line;
  1313. X        break;
  1314. X    case HM_ABS:
  1315. X        len = H_tail_base;
  1316. X        for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  1317. X        if (hist)
  1318. X        result = hist->line;
  1319. X        break;
  1320. X    }
  1321. X    if( echo )
  1322. X        fprintf(stderr, result ? "%s\n" : "History failed\n", result);
  1323. X    if( !result ) result="";
  1324. X    return result;
  1325. X}
  1326. X
  1327. Xvoid
  1328. Xreplace_head( char *str )
  1329. X{
  1330. X    if (str && strlen(str) && H_head) {
  1331. X        free (H_head->line);
  1332. X        H_head->line = malloc (strlen(str)+1);
  1333. X        strcpy (H_head->line, str);
  1334. X    }
  1335. X}
  1336. X
  1337. X
  1338. X#if 0
  1339. X#define CDLEN 20
  1340. Xstatic int   cd_len=CDLEN, cd_read, cd_write, cd_current;
  1341. Xstatic char *cd_hist[CDLEN];
  1342. X
  1343. Xadd_cdhist( char *str )
  1344. X{
  1345. X    if( !str )
  1346. X        return;
  1347. X    if( cd_hist[cd_write] )
  1348. X        free(cd_hist[cd_write]);
  1349. X    cd_hist[cd_write++]=str;
  1350. X    cd_write%=cd_len;
  1351. X    cd_current=cd_write;
  1352. X}
  1353. X
  1354. Xchar *
  1355. Xback_cdhist( void )
  1356. X{
  1357. X    if( cd_current!=cd_write ) cd_current= --cd_current % cd_len;
  1358. X    return cd_hist[cd_current];
  1359. X}
  1360. X
  1361. Xchar *
  1362. Xforw_cdhist( void )
  1363. X{
  1364. X    if( cd_current!=cd_read  ) cd_current= ++cd_current % cd_len;
  1365. X    return cd_hist[cd_current];
  1366. X}
  1367. X#endif
  1368. X
  1369. Xvoid
  1370. XpError(char *str )
  1371. X{
  1372. X    int ierr = (long)IoErr();
  1373. X    ierror(str, ierr);
  1374. X}
  1375. X
  1376. Xierror( char *str, int err )
  1377. X{
  1378. X    struct PERROR *per = Perror;
  1379. X
  1380. X    if (err) {
  1381. X        for (; per->errstr; ++per) {
  1382. X            if (per->errnum == err) {
  1383. X                fprintf (stderr, "%s%s%s\n",
  1384. X                per->errstr,
  1385. X                (str) ? ": " : "",
  1386. X                (str) ? str : "");
  1387. X                return err;
  1388. X            }
  1389. X        }
  1390. X        fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
  1391. X    }
  1392. X    return err;
  1393. X}
  1394. X
  1395. X/*
  1396. X * Disk directory routines
  1397. X *
  1398. X * dptr = dopen(name, stat)
  1399. X *    struct DPTR *dptr;
  1400. X *    char *name;
  1401. X *    int *stat;
  1402. X *
  1403. X * dnext(dptr, name, stat)
  1404. X *    struct DPTR *dptr;
  1405. X *    char **name;
  1406. X *    int  *stat;
  1407. X *
  1408. X * dclose(dptr)                  -may be called with NULL without harm
  1409. X *
  1410. X * dopen() returns a struct DPTR, or NULL if the given file does not
  1411. X * exist.  stat will be set to 1 if the file is a directory.  If the
  1412. X * name is "", then the current directory is openned.
  1413. X *
  1414. X * dnext() returns 1 until there are no more entries.  The **name and
  1415. X * *stat are set.  *stat = 1 if the file is a directory.
  1416. X *
  1417. X * dclose() closes a directory channel.
  1418. X *
  1419. X */
  1420. X
  1421. Xextern long IoError;
  1422. X
  1423. Xstruct DPTR *
  1424. Xdopen( char *name, int *stat)
  1425. X{
  1426. X    struct DPTR *dp;
  1427. X
  1428. X    *stat = 0;
  1429. X    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  1430. X    if (*name == '\0')
  1431. X        dp->lock = DupLock(Myprocess->pr_CurrentDir);
  1432. X    else
  1433. X        dp->lock = Lock (name,ACCESS_READ);
  1434. X    if (dp->lock == NULL) {
  1435. X        IoError=IoErr();
  1436. X        free (dp);
  1437. X        return NULL;
  1438. X    }
  1439. X    dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
  1440. X    if (!Examine (dp->lock, dp->fib)) {
  1441. X        pError (name);
  1442. X        dclose (dp);
  1443. X        return NULL;
  1444. X    }
  1445. X    if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
  1446. X    return dp;
  1447. X}
  1448. X
  1449. Xstatic int
  1450. Xdnext( struct DPTR *dp, char **pname, int *stat)
  1451. X{
  1452. X    if (dp == NULL) return (0);
  1453. X        if (ExNext (dp->lock, dp->fib)) {
  1454. X            *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  1455. X            *pname = dp->fib->fib_FileName;
  1456. X            return 1;
  1457. X        }
  1458. X    return 0;
  1459. X}
  1460. X
  1461. Xint
  1462. Xdclose( struct DPTR *dp )
  1463. X{
  1464. X    if (dp == NULL)
  1465. X        return 1;
  1466. X    if (dp->fib)
  1467. X        FreeMem (dp->fib,(long)sizeof(*dp->fib));
  1468. X    if (dp->lock)
  1469. X        UnLock (dp->lock);
  1470. X    free (dp);
  1471. X    return 1;
  1472. X}
  1473. X
  1474. X
  1475. Xint
  1476. Xisdir( char *file )
  1477. X{
  1478. X    struct DPTR *dp;
  1479. X    int stat;
  1480. X
  1481. X    stat = 0;
  1482. X    if (dp = dopen (file, &stat))
  1483. X        dclose(dp);
  1484. X    return (stat == 1);
  1485. X}
  1486. X
  1487. X
  1488. Xvoid
  1489. Xfree_expand( char **av )
  1490. X{
  1491. X    char **get = av;
  1492. X
  1493. X    if (av) {
  1494. X        while (*get)
  1495. X        free (*get++-sizeof(struct file_info));
  1496. X        free (av);
  1497. X    }
  1498. X}
  1499. X
  1500. X/*
  1501. X * EXPAND(base,pac)
  1502. X *    base           - char * (example: "df0:*.c")
  1503. X *    pac            - int  *  will be set to # of arguments.
  1504. X *
  1505. X * 22-May-87 SJD.  Heavily modified to allow recursive wild carding and
  1506. X *                 simple directory/file lookups. Returns a pointer to
  1507. X *                 an array of pointers that contains the full file spec
  1508. X *                 eg. 'df0:c/sear*' would result in : 'df0:C/Search'
  1509. X *
  1510. X *                 Now no longer necessary to Examine the files a second time
  1511. X *                 in do_dir since expand will return the full file info
  1512. X *                 appended to the file name. Set by formatfile().
  1513. X *                 eg. fullfilename'\0'rwed  NNNNNN NNNN  DD-MMM-YY HH:MM:SS
  1514. X *
  1515. X *                 Caller must call free_expand when done with the array.
  1516. X *
  1517. X * base             bname =       ename =
  1518. X * ------           -------       -------
  1519. X *  "*"               ""            "*"
  1520. X *  "!*.info"         ""            "*.info" (wild_exclude set)
  1521. X *  "su*d/*"          ""            "*"      (tail set)
  1522. X *  "file.*"          ""            "file.*"
  1523. X *  "df0:c/*"         "df0:c"       "*"
  1524. X *  ""                ""            "*"
  1525. X *  "df0:.../*"       "df0:"        "*"      (recur set)
  1526. X *  "df0:sub/.../*"   "df0:sub"     "*"      (recur set)
  1527. X *
  1528. X * ---the above base would be provided by execom.c or do_dir().
  1529. X * ---the below base would only be called from do_dir().
  1530. X *
  1531. X *  "file.c"          "file.c"      ""       if (dp == 0) fail else get file.c
  1532. X *  "df0:"            "df0:"        "*"
  1533. X *  "file/file"       "file/file"   ""       (dp == 0) so fail
  1534. X *  "df0:.../"        "df0:"        "*"      (recur set)
  1535. X *
  1536. X */
  1537. X
  1538. Xint expand_err;
  1539. X
  1540. Xchar **
  1541. Xexpand( char *base, int *pac )
  1542. X{
  1543. X    char *ptr;
  1544. X    char **eav = (char **)malloc(sizeof(char *) * (2));
  1545. X    short eleft, eac;
  1546. X    char *name;
  1547. X    char *bname, *ename, *tail;
  1548. X    int stat, recur, scr, bl;
  1549. X    struct DPTR *dp;
  1550. X
  1551. X    expand_err = *pac = recur = eleft = eac = 0;
  1552. X
  1553. X    base = strcpy(malloc(strlen(base)+1), base);
  1554. X    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  1555. X
  1556. X    if (!*ptr)   /* no wild cards */
  1557. X        --ptr;
  1558. X    else
  1559. X        for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  1560. X
  1561. X    if (ptr < base) {
  1562. X        bname = strcpy (malloc(1), "");
  1563. X    } else {
  1564. X        scr = ptr[1];
  1565. X        ptr[1] = '\0';
  1566. X        if (!strcmp(ptr-3,".../")) {
  1567. X            recur = 1;
  1568. X            *(ptr-3) = '\0';
  1569. X        }
  1570. X        bname = strcpy (malloc(strlen(base)+2), base);
  1571. X        ptr[1] = scr;
  1572. X    }
  1573. X    bl = strlen(bname);
  1574. X    ename = ++ptr;
  1575. X    for (; *ptr && *ptr != '/'; ++ptr);
  1576. X    scr = *ptr;
  1577. X    *ptr = '\0';
  1578. X    if (scr) ++ptr;
  1579. X    tail = ptr;
  1580. X
  1581. X    if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
  1582. X        free (bname);
  1583. X        free (base);
  1584. X        free (eav);
  1585. X        expand_err=1;
  1586. X        return (NULL);
  1587. X    }
  1588. X
  1589. X    if (!stat) {                /* eg. 'dir file' */
  1590. X        char *p,*s;
  1591. X        for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
  1592. X        if (s != bname) ++s;
  1593. X        *s ='\0';
  1594. X        eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
  1595. X        goto done;
  1596. X    }
  1597. X    if (!*ename) ename = "*";    /* eg. dir df0: */
  1598. X    if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
  1599. X        bname[bl] = '/';
  1600. X        bname[++bl] = '\0';
  1601. X    }
  1602. X    while ((dnext (dp, &name, &stat)) && !breakcheck()) {
  1603. X        int match = compare_ok(ename,name,0);
  1604. X        if (match && !(!recur && *tail)) {
  1605. X            if (eleft < 2) {
  1606. X                char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  1607. X                memmove (scrav, eav, (eac + 1) << 2);
  1608. X                free (eav);
  1609. X                eav = scrav;
  1610. X                eleft = 10;
  1611. X            }
  1612. X            eav[eac++] = svfile(bname,name,dp->fib);
  1613. X            --eleft;
  1614. X        }
  1615. X        if ((*tail && match) || recur) {
  1616. X            int alt_ac;
  1617. X            char *search, **alt_av, **scrav;
  1618. X            BPTR lock;
  1619. X
  1620. X            if (!stat)           /* expect more dirs, but this not a dir */
  1621. X                continue;
  1622. X            lock = CurrentDir (dp->lock);
  1623. X            search = malloc(strlen(ename)+strlen(name)+strlen(tail)+6);
  1624. X            strcpy (search, name);
  1625. X            strcat (search, "/");
  1626. X            if (recur) {
  1627. X                strcat(search, ".../");
  1628. X                strcat(search, ename);
  1629. X            }
  1630. X            strcat (search, tail);
  1631. X            scrav = alt_av = expand (search, &alt_ac);
  1632. X            free(search);
  1633. X            CurrentDir (lock);
  1634. X            if (scrav) {
  1635. X                while (*scrav) {
  1636. X                    int l;
  1637. X                    if (eleft < 2) {
  1638. X                        char **scrav = (char **)malloc(sizeof(char *)*(eac+10));
  1639. X                        memmove ( scrav, eav, (eac + 1) << 2);
  1640. X                        free (eav);
  1641. X                        eav = scrav;
  1642. X                        eleft = 10;
  1643. X                    }
  1644. X
  1645. X                    l = strlen(*scrav);
  1646. X                    eav[eac] = malloc(bl+l+1+sizeof(struct file_info));
  1647. X                    memcpy( eav[eac], *scrav-sizeof(struct file_info),
  1648. X                    sizeof(struct file_info));
  1649. X                    eav[eac]+=sizeof(struct file_info);
  1650. X                    strcpy( eav[eac], bname);
  1651. X                    strcat( eav[eac], *scrav);
  1652. X
  1653. X                    free (*scrav-sizeof(struct file_info));
  1654. X                    ++scrav;
  1655. X                    --eleft, ++eac;
  1656. X                }
  1657. X                free (alt_av);
  1658. X            }
  1659. X        }
  1660. X    }
  1661. Xdone:
  1662. X    dclose (dp);
  1663. X    *pac = eac;
  1664. X    eav[eac] = NULL;
  1665. X    free (bname);
  1666. X    free (base);
  1667. X    if (eac)
  1668. X        return (eav);
  1669. X    free (eav);
  1670. X    return (NULL);
  1671. X}
  1672. X
  1673. Xchar *
  1674. Xstrupr( char *s )
  1675. X{
  1676. X    char *old=s;
  1677. X    while (*s) *s=toupper(*s), s++;
  1678. X    return old;
  1679. X}
  1680. X
  1681. Xchar *
  1682. Xstrlwr( char *s )
  1683. X{
  1684. X    char *old=s;
  1685. X    while (*s) *s=tolower(*s), s++;
  1686. X    return old;
  1687. X}
  1688. X
  1689. X/*
  1690. X * Compare a wild card name with a normal name
  1691. X */
  1692. X
  1693. Xint
  1694. Xcompare_ok( char *wild, char *name, int casedep)
  1695. X{
  1696. X    int queryflag;
  1697. X    char buf[260], wildbuf[260], *lowname;
  1698. X
  1699. X    if (queryflag=(*wild=='&')) wild++;
  1700. X    if (*wild=='!') *wild='~';
  1701. X
  1702. X    if (! casedep) {
  1703. X        strupr(wild);
  1704. X        strcpy(buf,name);
  1705. X        strupr(buf);
  1706. X        lowname=buf;
  1707. X    } else
  1708. X        lowname=name;
  1709. X
  1710. X    PreParse(wild, wildbuf);
  1711. X    if ( ! PatternMatch(wildbuf,lowname)) return 0;
  1712. X
  1713. X    if (queryflag) {
  1714. X        printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
  1715. X        gets(buf);
  1716. X        return (toupper(*buf)=='Y');
  1717. X    }
  1718. X    return 1;
  1719. X}
  1720. X
  1721. Xstatic char *
  1722. Xsvfile( char *s1, char *s2, FIB *fib)
  1723. X{
  1724. X    int len=strlen(s1)+strlen(s2)+1;
  1725. X    char *p = malloc (len+sizeof(struct file_info));
  1726. X    struct file_info *info;
  1727. X
  1728. X    info=(struct file_info *)p;
  1729. X    p+=sizeof(struct file_info);
  1730. X    strcpy(p, s1);
  1731. X    strcat(p, s2);
  1732. X    info->flags = fib->fib_Protection;
  1733. X    if( fib->fib_DirEntryType<0 ) {
  1734. X        info->size  = fib->fib_Size;
  1735. X        info->blocks= fib->fib_NumBlocks;
  1736. X    } else {
  1737. X        info->size  = -1;
  1738. X        info->blocks= 0;
  1739. X    }
  1740. X    if( fib->fib_Comment[0] )
  1741. X        info->flags|= 1<<30;
  1742. X    info->date=fib->fib_Date;
  1743. X    info->class[0]=1;
  1744. X    return p;
  1745. X}
  1746. X
  1747. X
  1748. X
  1749. Xstatic FILE *out;
  1750. Xstatic int NumDirs;
  1751. X
  1752. Xvoid
  1753. Xexpand_all( char *name, FILE *file )
  1754. X{
  1755. X    BPTR lock;
  1756. X    char path[300];
  1757. X    FIB  *fib;
  1758. X
  1759. X    out=file;
  1760. X    printf( " %s\n", name );
  1761. X    NumDirs=0;
  1762. X
  1763. X    if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) {
  1764. X        if( lock=Lock( name, ACCESS_READ )) {
  1765. X            strcpy( path, name );
  1766. X            exall( lock, path );
  1767. X            printf( "\n", NumDirs );
  1768. X        }
  1769. X        FreeMem(fib,sizeof(struct FileInfoBlock));
  1770. X    }
  1771. X}
  1772. X
  1773. Xstatic int
  1774. Xexall( BPTR lock, char *path )
  1775. X{
  1776. X    BPTR old, sublock;
  1777. X    int len;
  1778. X    struct FileInfoBlock *fib;
  1779. X
  1780. X    old=CurrentDir( lock );
  1781. X
  1782. X    if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) )
  1783. X        return 1;
  1784. X
  1785. X    len=strlen( path );
  1786. X    Examine( lock, fib );
  1787. X    while( ExNext( lock, fib ) ) {
  1788. X        if( fib->fib_DirEntryType>=0 )
  1789. X            if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) {
  1790. X                if( !len || path[len-1]==':' )
  1791. X                    sprintf(path+len,"%s",  fib->fib_FileName);
  1792. X                else 
  1793. X                    sprintf(path+len,"/%s", fib->fib_FileName);
  1794. X                fprintf( out, "%s\n", path );
  1795. X                fprintf( stdout, " Directories: %d\015", ++NumDirs );
  1796. X                fflush ( stdout );
  1797. X                if(exall( sublock, path ))
  1798. X                    break;
  1799. X                path[len]=0;
  1800. X            }
  1801. X    }
  1802. X    FreeMem( fib, sizeof(struct FileInfoBlock));
  1803. X    CurrentDir( old );
  1804. X    return dobreak();
  1805. X}
  1806. X
  1807. X
  1808. X
  1809. X/* Sort routines */
  1810. X
  1811. Xint reverse;
  1812. X
  1813. Xint
  1814. Xcmp( char *s1, char *s2)
  1815. X{
  1816. X    int r=Strcmp(s1, s2);
  1817. X    return reverse ? -r : r;
  1818. X}
  1819. X
  1820. Xint
  1821. Xsizecmp( char *s1, char *s2)
  1822. X{
  1823. X    int r= ((struct file_info *)(s2-sizeof(struct file_info)))->size -
  1824. X           ((struct file_info *)(s1-sizeof(struct file_info)))->size;
  1825. X    return reverse ? -r : r;
  1826. X}
  1827. X
  1828. Xint
  1829. Xdatecmp( char *s1, char *s2 )
  1830. X{
  1831. X    int r;
  1832. X    struct DateStamp
  1833. X      *d1=&((struct file_info *)(s1-sizeof(struct file_info)))->date,
  1834. X      *d2=&((struct file_info *)(s2-sizeof(struct file_info)))->date;
  1835. X    if( !(r= d2->ds_Days - d1->ds_Days))
  1836. X        if( !(r=d2->ds_Minute - d1->ds_Minute ) )
  1837. X            r=d2->ds_Tick - d1->ds_Tick;
  1838. X    return reverse ? -r : r;
  1839. X}
  1840. X
  1841. X
  1842. Xstatic void
  1843. Xenterclass( FILEINFO *info )
  1844. X{
  1845. X    char *class, *iclass=info->class, *t;
  1846. X
  1847. X    if( *iclass==1 ) {
  1848. X        if( class=getclass( (char *)(info+1))) {
  1849. X            strncpy( iclass, class, 11 );
  1850. X            iclass[11]=0;
  1851. X            if( t=index(iclass,0xA0))
  1852. X                *t=0;
  1853. X        } else 
  1854. X            iclass[0]=0;
  1855. X    }
  1856. X}
  1857. X
  1858. Xint
  1859. Xclasscmp( char *s1, char *s2 )
  1860. X{
  1861. X    int r;
  1862. X    FILEINFO *info1=(FILEINFO *)s1-1, *info2=(FILEINFO *)s2-1;
  1863. X
  1864. X    enterclass( info1 );
  1865. X    enterclass( info2 );
  1866. X
  1867. X    r= Strcmp( info1->class, info2->class );
  1868. X    if( !r ) r=Strcmp(s1, s2);
  1869. X    return reverse ? -r : r;
  1870. X}
  1871. X
  1872. X
  1873. Xvoid
  1874. XQuickSort( char *av[], int n)
  1875. X{
  1876. X    DirQuickSort( av, n, cmp, 0 );
  1877. X}
  1878. X
  1879. Xstatic int (*compare)(char *, char *);
  1880. X
  1881. Xvoid
  1882. XDirQuickSort( char *av[], int n, int (*func)(char *,char *), int rev)
  1883. X{
  1884. X    reverse=rev; compare=func;
  1885. X    quicksort( av, n-1 );
  1886. X}
  1887. X
  1888. Xstatic void
  1889. Xquicksort( char **av, int n )
  1890. X{
  1891. X    char **i, **j, *x, *t;
  1892. X
  1893. X
  1894. X    if( n>0 ) {
  1895. X        i=av; j=av+n; x=av[ n>>1 ];
  1896. X        do {
  1897. X            while( (*compare)(*i,x)<0 ) i++;
  1898. X            while( (*compare)(x,*j)<0 ) --j;
  1899. X            if( i<=j )
  1900. X                { t=*i; *i=*j; *j=t; i++; j--; }
  1901. X        } while( i<=j );
  1902. X
  1903. X        if( j-av < av+n-i ) {
  1904. X            quicksort( av, j-av  );
  1905. X            quicksort( i , av+n-i);
  1906. X        } else {
  1907. X            quicksort( i , av+n-i);
  1908. X            quicksort( av, j-av  );
  1909. X        }
  1910. X    }
  1911. X}
  1912. X
  1913. X
  1914. Xint
  1915. Xfilesize( char *name )
  1916. X{
  1917. X    BPTR lock;
  1918. X    struct FileInfoBlock *fib;
  1919. X    int  len=0;
  1920. X
  1921. X    if( lock = Lock (name,ACCESS_READ)) {
  1922. X        if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
  1923. X            if (Examine (lock, fib))
  1924. X                len=fib->fib_Size;
  1925. X            FreeMem( fib, sizeof(*fib));
  1926. X        }
  1927. X        UnLock(lock);
  1928. X    }
  1929. X    return len;
  1930. X}
  1931. X
  1932. X
  1933. X#ifndef MIN
  1934. X#define MIN(x,y) ((x)<(y)?(x):(y))
  1935. X#endif
  1936. X
  1937. Xchar **
  1938. Xand( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1939. X{
  1940. X    char **av=(char **)malloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
  1941. X    int i, j, k=0;
  1942. X
  1943. X    for( i=0; i<ac1; i++ )
  1944. X        for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  1945. X            if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j]))
  1946. X                av[k++]=av1[i];
  1947. X    *ac=k;
  1948. X    return av;
  1949. X}
  1950. X
  1951. Xchar **
  1952. Xwithout( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1953. X{
  1954. X    char **av=(char **)malloc(ac1*sizeof(char *) ), *str;
  1955. X    int i, j, k=0;
  1956. X
  1957. X    for( i=0; i<ac1; i++ ) {
  1958. X        for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
  1959. X            if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) )
  1960. X                break;
  1961. X        if( j==ac2 )
  1962. X            av[k++]=av1[i];
  1963. X    }
  1964. X    *ac=k;
  1965. X    return av;
  1966. X}
  1967. X
  1968. Xchar **
  1969. Xor( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
  1970. X{
  1971. X    char **av=(char **)malloc((ac1+ac2)*sizeof(char *) ), *str;
  1972. X    int i, j, k=0;
  1973. X
  1974. X    for( i=0; i<ac1; i++ )
  1975. X        av[k++]=av1[i];
  1976. X
  1977. X    for( i=0; i<ac2; i++ ) {
  1978. X        for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ )
  1979. X            if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) )
  1980. X                break;
  1981. X        if( j==ac1 )
  1982. X            av[k++]=av2[i];
  1983. X    }
  1984. X
  1985. X    *ac=k;
  1986. X    return av;
  1987. X}
  1988. X
  1989. Xvoid
  1990. Xclear_archive_bit( char *name )
  1991. X{
  1992. X    struct DPTR *dp;
  1993. X    int stat;
  1994. X
  1995. X    if(dp = dopen(name,&stat) ) {
  1996. X        SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
  1997. X        dclose( dp );
  1998. X    }
  1999. X}
  2000. X
  2001. Xchar *
  2002. Xitoa( int i )
  2003. X{
  2004. X    static char buf[20];
  2005. X    char *pos=buf+19;
  2006. X    int count=4, flag=0;
  2007. X
  2008. X    if( i<0 )
  2009. X        flag=1, i=-i;
  2010. X
  2011. X    do {
  2012. X        if( !--count )
  2013. X            count=3, *--pos='\'';
  2014. X        *--pos= i%10+'0';
  2015. X    } while( i/=10 );
  2016. X
  2017. X    if( flag )
  2018. X        *--pos='-';
  2019. X
  2020. X    return pos;
  2021. X}
  2022. X
  2023. Xchar *
  2024. Xitok( int i )
  2025. X{
  2026. X    static char buf[16], which;
  2027. X    char *exp=" KMG", *ptr= buf+(which=8-which);
  2028. X
  2029. X    do
  2030. X        i=(i+512)/1024, exp++;
  2031. X    while( i>1024 );
  2032. X    sprintf( ptr,"%d%c",i,*exp);
  2033. X
  2034. X    return ptr;
  2035. X}
  2036. X
  2037. Xchar *
  2038. Xnext_a0( char *str )
  2039. X{
  2040. X    while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++;
  2041. X    return *str ? str+1 : NULL;
  2042. X}
  2043. X
  2044. Xstatic int
  2045. Xgethex( char *str, int l )
  2046. X{
  2047. X    int i, val=0, n, c;
  2048. X
  2049. X    if( *str=='.' ) return l==2 ? 256 : 0;
  2050. X
  2051. X    for( i=0; i<l || !l; i++ ) {
  2052. X        c=*str++;
  2053. X        if     ( c>='0' && c<='9' ) n=c-'0';
  2054. X        else if( c>='a' && c<='f' ) n=c-'a'+10;
  2055. X        else if( c>='A' && c<='F' ) n=c-'A'+10;
  2056. X        else break;;
  2057. X        val=16*val+n;
  2058. X    }
  2059. X    return (l && i!=l) ? -1 : val;
  2060. X}
  2061. X
  2062. Xstrwrdcmp( char *str, char *wrd )
  2063. X{
  2064. X    int len1=strlen(str);
  2065. X    char *ind=index(wrd,0xA0);
  2066. X    if( ind )
  2067. X        return len1!=ind-wrd || Strncmp(str,wrd,len1);
  2068. X    else 
  2069. X        return Strcmp(str,wrd);
  2070. X
  2071. X}
  2072. X
  2073. Xint
  2074. Xwrdlen( char *str )
  2075. X{
  2076. X    char *old=str;
  2077. X
  2078. X    while( *str && *str!=0xA0 ) str++;
  2079. X    return str-old;
  2080. X}
  2081. X
  2082. Xchar *classfile;
  2083. X
  2084. Xchar *
  2085. Xgetclass(char *file)
  2086. X{
  2087. X    CLASS *cl;
  2088. X    char *class, *str, *arg, *get, *buf;
  2089. X    int offs, byte, len, fail;
  2090. X    BPTR fh;
  2091. X
  2092. X    if( classfile ) {
  2093. X        char buf[80];
  2094. X        sprintf(buf,"source %s",classfile);
  2095. X        execute(buf);
  2096. X        classfile=0;
  2097. X    }
  2098. X
  2099. X    if( isdir(file) ) return "dir";
  2100. X
  2101. X    if( !(buf=calloc(1024,1))) return NULL;
  2102. X    if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
  2103. X    len=Read( fh,buf,1023);
  2104. X    Close(fh);
  2105. X
  2106. X    for( cl=CRoot; cl; cl=cl->next ) {
  2107. X        class=cl->name;
  2108. X        if(!(str=next_a0(cl->name))) continue;
  2109. X        while( str ) {
  2110. X            if(!(arg=next_a0( str ))) goto nextclass;
  2111. X            switch( *str ) {
  2112. X            case 's':
  2113. X                if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
  2114. X                if( !strwrdcmp(file+offs,arg)) goto found;
  2115. X                break;
  2116. X            case 'n':
  2117. X                if( !strwrdcmp(BaseName(file),arg) ) goto found;
  2118. X                break;
  2119. X            case 'd':
  2120. X                goto found;
  2121. X            case 'o':
  2122. X                offs=gethex(arg,0);
  2123. X                if( !(arg=index(arg,','))) goto nextclass;
  2124. X                if( offs>len-10 ) break;
  2125. X                for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
  2126. X                    if( *get++!=byte && byte!=256 )
  2127. X                        goto nexttry;
  2128. X                goto found;
  2129. X            case 'c':
  2130. X                if( !len )
  2131. X                    goto nexttry;
  2132. X                for( get=buf, fail=0; get<buf+len; get++ )
  2133. X                    if( *get<9 || *get>13 && *get<32 || *get>127  )
  2134. X                        fail++;
  2135. X                if( fail*8>len )
  2136. X                    goto nexttry;
  2137. X                goto found;
  2138. X            case 'a':
  2139. X                goto nextclass;
  2140. X            default:
  2141. X                goto nextclass;
  2142. X            }
  2143. Xnexttry:    str=next_a0(arg);
  2144. X        }
  2145. Xnextclass: ;
  2146. X    }
  2147. X
  2148. X    free(buf);
  2149. X    return NULL;
  2150. X
  2151. Xfound:
  2152. X    free(buf);
  2153. X    return class;
  2154. X}
  2155. X
  2156. Xchar *
  2157. Xgetaction( char *class, char *action )
  2158. X{
  2159. X    CLASS *cl;
  2160. X    char *cur, *ind;
  2161. X    int len;
  2162. X
  2163. X    for( len=0; class[len] && class[len]!=0xA0; len++ ) ;
  2164. X    for( cl=CRoot; cl; cl=cl->next ) {
  2165. X        if( strncmp( cur=cl->name,class,len+1 ))
  2166. X            continue;
  2167. X        do
  2168. X            cur=index( cur,0xA0 );
  2169. X        while( cur && *++cur!='a');
  2170. X
  2171. X        if( cur && (cur=index( ++cur,0xA0 ))) {
  2172. X            do {
  2173. X                if( !(ind=index( ++cur,'=' )))
  2174. X                    return NULL;
  2175. X                len=ind-cur;
  2176. X                if( len==strlen(action) && !strncmp(action,cur,len))
  2177. X                    return ++ind;
  2178. X            } while( cur=index(cur,0xA0) );
  2179. X        }
  2180. X    }
  2181. X    return NULL;
  2182. X}
  2183. X
  2184. Xint
  2185. Xdoaction( char *file, char *action, char *args )
  2186. X{
  2187. X    char *class, *com, *c, *copy;
  2188. X
  2189. X    if( !(class=getclass(file)))
  2190. X        return 10;
  2191. X    if( !(com=getaction(class,action)))
  2192. X        return 11;
  2193. X    if( c=index(com,0xA0) )
  2194. X        *c=0;
  2195. X    copy=malloc( strlen(com)+strlen(file)+strlen(args)+5 );
  2196. X    sprintf(copy,"%s %s %s",com,file,args);
  2197. X    execute(copy);
  2198. X    free(copy);
  2199. X    if( c )
  2200. X        *c=0xA0;
  2201. X    return 0;
  2202. X}
  2203. END_OF_FILE
  2204. if test 21051 -ne `wc -c <'sub.c'`; then
  2205.     echo shar: \"'sub.c'\" unpacked with wrong size!
  2206. fi
  2207. # end of 'sub.c'
  2208. fi
  2209. echo shar: End of archive 2 \(of 6\).
  2210. cp /dev/null ark2isdone
  2211. MISSING=""
  2212. for I in 1 2 3 4 5 6 ; do
  2213.     if test ! -f ark${I}isdone ; then
  2214.     MISSING="${MISSING} ${I}"
  2215.     fi
  2216. done
  2217. if test "${MISSING}" = "" ; then
  2218.     echo You have unpacked all 6 archives.
  2219.     rm -f ark[1-9]isdone
  2220. else
  2221.     echo You still need to unpack the following archives:
  2222.     echo "        " ${MISSING}
  2223. fi
  2224. ##  End of shell archive.
  2225. exit 0
  2226. -- 
  2227. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  2228. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  2229. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  2230.